package main

import (
	"mapreduce/mr"
	"strconv"
	"strings"
	"unicode"
)

func main() {
	mr.Worker(Map, Reduce)
}

// Map 函数将为每个输入文件调用一次，第一个参数是输入文件的名称，第二个参数是文件的全部内容
// 您应该忽略输入文件名称，仅查看contents参数
// 返回值是一个键值对的切片
func Map(filename string, contents string) []mr.KeyValue {
	// function to detect word separators.
	// 判断 rune 是否为字母
	ff := func(r rune) bool { return !unicode.IsLetter(r) }

	// split contents into an array of words.
	// 依据上面的匿名函数 ff，下面是将非字母的字符串作为分割点
	// 即分割单词，返回字符串切片，就是一个个的单词
	words := strings.FieldsFunc(contents, ff)
	// 创建一个键值对切片
	kva := []mr.KeyValue{}
	for _, w := range words { // 遍历单词集合，每个单词作为作为Key，value 统一为 1
		kv := mr.KeyValue{w, "1"}
		kva = append(kva, kv)
	}
	return kva
}

// The reduce function is called once for each key generated by the
// map tasks, with a list of all the values created for that key by
// any map task.

// Reduce "reduce" 函数会针对 map 任务生成的每一个键调用一次，
// 该函数会接收一个包含该键所有对应值的列表作为参数，
// 这些值由任何一个 map 任务创建。
func Reduce(key string, values []string) string {
	// return the number of occurrences of this word.
	return strconv.Itoa(len(values))
}
